package com.hd.service.activiti.example.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.hd.commons.exception.MyException;
import com.hd.dao.BaseDao;
import com.hd.entity.activiti.BaseVO;
import com.hd.entity.activiti.CommentEntity;
import com.hd.entity.activiti.ProcessInstanceEntity;
import com.hd.entity.activiti.example.SendDocument;
import com.hd.entity.sys.User;
import com.hd.service.activiti.ActStartRightService;
import com.hd.service.activiti.ActivitiService;
import com.hd.service.activiti.CommentEntityService;
import com.hd.service.activiti.example.SendDocumentService;
import com.hd.service.impl.BaseServiceImpl;
import com.hd.service.sys.UserService;
import com.hd.util.StringUtils;
import com.hd.util.result.PageInfo;
@Service("sendDocumentSerice")
public class SendDocumentServiceImpl extends BaseServiceImpl<SendDocument, String> implements SendDocumentService {
	@Autowired
	private BaseDao<SendDocument,String>sendDocumentDao;
	@Autowired
	private IdentityService identityService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	private ActivitiService activitiService;
	@Autowired
	private ActStartRightService actStartRightService;
	@Autowired
	private BaseDao<ProcessInstanceEntity,String>processInstanceEntityDao;
	@Autowired
	private CommentEntityService commentEntityService;
	@Autowired
	private UserService userService;
	@Override
	public Serializable save(SendDocument sendDocument) {
		try {
			sendDocument.setId(UUID.randomUUID().toString());
			return this.add(sendDocument);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	@Override
	public void update(SendDocument sendDocument) {
		try {
			this.saveOrUpdate(sendDocument);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void deleteByProcessInstanceId(String processInstanceId) {
		String hql="delete from SendDocument where processInstanceId=?";
		sendDocumentDao.execute(hql, processInstanceId);
	}

	@Override
	public SendDocument getByProcessInstanceId(String processInstanceId) {
		String hql="from SendDocument where processInstanceId=?";
		List<SendDocument>SendDocuments=sendDocumentDao.find(hql, processInstanceId);
		if(SendDocuments.size()>0) {
			return SendDocuments.get(0);
		}
		return null;
	}

	@Override
	public String startProcessInstance(String processDefKey,SendDocument sendDocument) {
		//判断是否有权限启动流程
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefKey).singleResult();
		Boolean hasAuthenticated = actStartRightService.hasAuthenticated(processDefinition.getId(), sendDocument.getUserid());
		if(!hasAuthenticated) {
			sendDocumentDao.delete(sendDocument);
			throw new MyException("你没有权限启动该流程");
		}
		  // 用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中
        identityService.setAuthenticatedUserId(sendDocument.getUserid().toString());
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("entity", sendDocument);
        variables.put("prevUserid", sendDocument.getPrevUserid());
        String businessKey = sendDocument.getBusinessKey_();
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefKey, businessKey, variables);
        String processInstanceId = processInstance.getId();
        sendDocument.setProcessInstanceId(processInstanceId);
        this.sendDocumentDao.update(sendDocument);
        //最后要设置null，就是这么做，还没研究为什么
        this.identityService.setAuthenticatedUserId(null);
        return processInstanceId;
	}

	@Override
	public void selectDataGrid(PageInfo pageInfo) {
		 String hql="from SendDocument where 1=1 and userid=?";
	        Map<String,Object>condition=pageInfo.getCondition();
	        List<Object> params=new ArrayList<Object>();
	        params.add(condition.get("userid"));
				if(!StringUtils.isNull(condition.get("status"))) {
	            hql+=" and status=?";
	            params.add(condition.get("status"));
	        }
				if(!StringUtils.isNull(condition.get("title"))) {
	            hql+=" and title=?";
	            params.add(condition.get("title"));
	        }
			if(!StringUtils.isNull(condition.get("processInstanceId"))) {
	            hql+=" and processInstanceId=?";
	            params.add(condition.get("processInstanceId"));
	        }
			if(!StringUtils.isNull(condition.get("sendDateStart"))) {
				hql+=" and sendDate>=?";
				params.add(condition.get("sendDateStart"));
			}
			if(!StringUtils.isNull(condition.get("sendDateEnd"))) {
				hql+=" and sendDate<=?";
				params.add(condition.get("sendDateEnd"));
			}
	        
	        hql+=" order by status asc";
	        List<SendDocument> sendDocuments=sendDocumentDao.findPage(hql, pageInfo.getNowpage(), pageInfo.getPagesize(),params);
	        //设置任务执行人
	        if(sendDocuments.size()>0) {
	        	for(SendDocument sendDocument:sendDocuments) {
	        		if(sendDocument.getStatus().equals(BaseVO.APPROVAL_ADJUST)||sendDocument.getStatus().equals(BaseVO.PENDING)) {
	        			Map<String, Object> map = activitiService.findTodoTaskAssigneeOrCandidateUsers(sendDocument.getProcessInstanceId());
	        			String taskAssigneeOrCandidateUsers = (String) map.get("userNames");
	        			sendDocument.setAssigneeOrCandidateUser(taskAssigneeOrCandidateUsers);
	        			sendDocument.setTaskName((String)map.get("taskName"));
	        		}
	        	}
	        }
	        pageInfo.setRows(sendDocuments);
			String countHql="select count(*) "+hql;
			int total=Integer.parseInt(sendDocumentDao.getCountByList(countHql,params).toString());
	        pageInfo.setTotal(total);
		
	}

	@Override
	public SendDocument get(String id) {
		return sendDocumentDao.get(SendDocument.class, id);
	}

	@Override
	public void delete(String id) {
		sendDocumentDao.delete(SendDocument.class, id);
	}

	/**
	 * 作废流程
	 */
	@Override
	public void deleteSendDocumentProcess(String processInstanceId) {
		ProcessInstanceEntity processInstanceEntity = processInstanceEntityDao.get(ProcessInstanceEntity.class, processInstanceId);
		if((processInstanceEntity.getStatus()==processInstanceEntity.FAIL_STATUS)||processInstanceEntity.getStatus()==processInstanceEntity.COMPLETE_STATUS) {
			throw new MyException("流程【"+processInstanceId+"】已审批结束，不能作废");
		}
		if(processInstanceEntity.getStatus()!=processInstanceEntity.INVALID) {
			runtimeService.suspendProcessInstanceById(processInstanceId);//挂起流程
			runtimeService.deleteProcessInstance(processInstanceId,"作废流程");//删除流程
			String hql="update SendDocument set status=? where processInstanceId=?";
			sendDocumentDao.execute(hql, BaseVO.INVALID,processInstanceId);
			 hql="update ProcessInstanceEntity set status=? where processInstanceId=?";
			 processInstanceEntityDao.execute(hql,ProcessInstanceEntity.INVALID_STATUS,processInstanceId);
			 doInvalidComment(processInstanceEntity.getUserid(),processInstanceId);
		}
	}
	  //作废流程信息
		protected void doInvalidComment(String userId,String processInstanceId){
			CommentEntity commentEntity=new CommentEntity();
			commentEntity.setTime(new Date());
			commentEntity.setType(CommentEntity.COMMENT_INVALID);
			User user = userService.get(userId);
			if (user != null) {
				commentEntity.setUserName(user.getName());
			}
			commentEntity.setUserid(userId);
			commentEntity.setProcessInstanceId(processInstanceId);
			String	comment=user.getName()+"作废流程【"+processInstanceId+"】";
			commentEntity.setComment(comment);
			commentEntityService.save(commentEntity);
		}
}
